package com.note.feng.leetcode.algorithms.easy.six;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class SixHundredThirtySeven {
    /**
     * 637 二叉树的层平均值
     * 给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。
     *
     * 示例 1：
     *
     * 输入：root = [3,9,20,null,null,15,7]
     * 输出：[3.00000,14.50000,11.00000]
     * 解释：第 0 层的平均值为 3,第 1 层的平均值为 14.5,第 2 层的平均值为 11 。
     * 因此返回 [3, 14.5, 11] 。
     * 示例 2:
     *
     * 输入：root = [3,9,20,15,7]
     * 输出：[3.00000,14.50000,11.00000]
     *
     * 提示：
     *
     * 树中节点数量在 [1, 104] 范围内
     * -231 <= Node.val <= 231 - 1
     *
     * 来源：力扣（LeetCode）
     * 链接：https://leetcode.cn/problems/average-of-levels-in-binary-tree
     */
    /**
     * 解法：按照层级遍历二叉树
     * 借助队列，存储每层的节点，并累加节点的值，统计节点的数量，
     * 遍历完每层后，计算出该层的平均值，存储在 list 中
     * 注意：累计过程中出现 int 超出范围
     * @param root
     * @return
     */
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> res = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        res.add(Double.valueOf(root.val));
        while (true){
            Queue<TreeNode> tmp = new LinkedList<>();
            double sum = 0;
            int size = 0;
            while (!queue.isEmpty()){
                TreeNode node = queue.poll();
                if(node.left != null){
                    tmp.offer(node.left);
                    sum += node.left.val;
                    size ++;
                }
                if(node.right != null){
                    tmp.offer(node.right);
                    sum += node.right.val;
                    size ++;
                }
            }
            if(size > 0){
                res.add(sum / size);
            }
            if(tmp.isEmpty()){
                break;
            }
            queue = tmp;
        }
        return res;
    }

    public class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode() {}
      TreeNode(int val) { this.val = val; }
      TreeNode(int val, TreeNode left, TreeNode right) {
          this.val = val;
          this.left = left;
          this.right = right;
      }
    }
}
